--[[	$Id: caelNameplates.lua 3451 2013-08-02 15:55:22Z sdkyron@gmail.com $	]]

local _, caelNameplates = ...

caelNameplates.eventFrame = CreateFrame("Frame", nil, UIParent)

if not IsAddOnLoaded("caelCore") then
	SetCVar("bloattest", 0) -- 1 might make nameplates larger but it fixes the disappearing ones.
	SetCVar("bloatnameplates", 0) -- 1 makes nameplates larger depending on threat percentage.
	SetCVar("bloatthreat", 0) -- 1 makes nameplates resize depending on threat gain/loss. Only active when a mob has multiple units on its threat table.
end

local iconTexture = caelMedia.files.buttonNormal
local raidIcons = caelMedia.files.raidIcons
local overlayTexture = [=[Interface\Tooltips\Nameplate-Border]=]

local select = select, r, g, b

local pixelScale = caelLib.scale

local UpdateTime = function(self, curValue)
	local minValue, maxValue = self:GetMinMaxValues()
	if self.channeling then
		self.time:SetFormattedText("%.1f ", curValue)
	else
		self.time:SetFormattedText("%.1f ", maxValue - curValue)
	end
end

local RoundValue = function(value)
	return floor(value * (10 ^ 2) + 0.5) / 10 ^ 2
end

local HealthUpdate = function(self, elapsed)
	self.lastUpdate = self.lastUpdate + elapsed

	if self.lastUpdate >= 0.2 then
		if not self.oldglow:IsShown() then
			self.hpGlow:SetBackdropBorderColor(0, 0, 0)
		else
			r, g, b = self.oldglow:GetVertexColor()

			if g + b == 0 then
				self.hpGlow:SetBackdropBorderColor(1, 0, 0)
			else
				self.hpGlow:SetBackdropBorderColor(1, 1, 0)
			end
		end

		r, g, b = self:GetStatusBarColor()

		if not (RoundValue(r) == 0.53 and RoundValue(g) == 0.53 and RoundValue(b) == 0.53) then
			self:SetStatusBarColor(self.r, self.g, self.b)
		end

		self.lastUpdate = 0
	end
end

local UpdatePlateColor = function(self, r, g, b)
	local newr, newg, newb

	if g + b == 0 then
		-- Hostile unit
		newr, newg, newb = 0.69, 0.31, 0.31
	elseif r + b == 0 then
		-- Friendly unit
		newr, newg, newb = 0.33, 0.59, 0.33
	elseif r + g == 0 then
		-- Friendly player
		newr, newg, newb = 0.31, 0.45, 0.63
	elseif 2 - (r + g) < 0.05 and b == 0 then
		-- Neutral unit
		newr, newg, newb = 0.65, 0.63, 0.35
	else
		-- Hostile player - class colored.
		newr, newg, newb = self:GetStatusBarColor()
	end

	return newr, newg, newb
end

local UpdatePlate = function(self)
	local barScale = self.barFrame:GetScale()

	self.healthBar.r, self.healthBar.g, self.healthBar.b = UpdatePlateColor(self.healthBar, self.healthBar:GetStatusBarColor())
	self.healthBar:SetStatusBarColor(self.healthBar.r, self.healthBar.g, self.healthBar.b)
	self.healthBar.hpBackground:SetVertexColor(self.healthBar.r * 0.33, self.healthBar.g * 0.33, self.healthBar.b * 0.33, 0.75)
	self.healthBar.lastUpdate = 0

	self.healthBar:ClearAllPoints()
	self.healthBar:SetPoint("CENTER", self.healthBar:GetParent())
	self.healthBar:SetHeight(pixelScale(5 / barScale))
	self.healthBar:SetWidth(pixelScale(100 / barScale))

	self.castBar.IconOverlay:SetVertexColor(self.healthBar.r, self.healthBar.g, self.healthBar.b)

	self.highlight:ClearAllPoints()
	self.highlight:SetAllPoints(self.healthBar)

	local oldName = self.oldname:GetText()
	local newName = (string.len(oldName) > 20) and string.gsub(oldName, "%s?(.[\128-\191]*)%S+%s", "%1. ") or oldName -- "%s?(.)%S+%s"

	self.name:SetText(newName)

	local level, elite, mylevel = tonumber(self.level:GetText()), self.elite:IsShown(), UnitLevel("player")

	self.level:ClearAllPoints()
	self.level:SetPoint("RIGHT", self.healthBar, "LEFT", pixelScale(-2 / barScale), 0)
	self.level:SetFont(caelMedia.fonts.CAELNAMEPLATE_FONT, (9 * UIParent:GetScale() / barScale))
	self.level:SetShadowOffset(1.25, -1.25)

	if self.boss:IsShown() then
		self.level:SetText("??")
		self.level:SetTextColor(0.8, 0.05, 0)
		self.level:Show()
	elseif not elite and level == mylevel then
		self.level:Hide()
	else
		self.level:SetText(level..(elite and "+" or ""))
	end
end

local FixCastbar = function(self)
	self.castbarOverlay:Hide()

	if floor(self:GetHeight() + 0.5) ~= pixelScale(5) then
		self:ClearAllPoints()
		self:SetPoint("TOP", self.healthBar, "BOTTOM", 0, pixelScale(-4))
		self:SetSize(pixelScale(100), pixelScale(5))

		while self:GetEffectiveScale() < 1 do
			self:SetScale(self:GetScale() + 0.01)
		end

		while self:GetEffectiveScale() > 1 do
			self:SetScale(self:GetScale() - 0.01)
		end
	end
end

local ColorCastBar = function(self, shielded)
	if shielded then
		self:SetStatusBarColor(0.8, 0.05, 0)
		self.cbGlow:SetBackdropBorderColor(0.75, 0.75, 0.75)
	else
		self.cbGlow:SetBackdropBorderColor(0, 0, 0)
	end
end

local OnShow = function(self)
	self.channeling  = UnitChannelInfo("target")

	ColorCastBar(self, self.shieldedRegion:IsShown())
	self.IconOverlay:Show()
end

local OnValueChanged = function(self, curValue)
	UpdateTime(self, curValue)
end

local OnHide = function(self)
	self.highlight:Hide()
	self.healthBar.hpGlow:SetBackdropBorderColor(0, 0, 0)
end

local OnEvent = function(self, event, unit)
	if unit == "target" then
		if self:IsShown() then
			ColorCastBar(self, event == "UNIT_SPELLCAST_NOT_INTERRUPTIBLE")
		end
	end
end

local CreatePlate = function(frame)
	frame.done = true

	frame.barFrame, frame.nameFrame = frame:GetChildren()
	frame.healthBar, frame.castBar = frame.barFrame:GetChildren()

	local healthBar, castBar = frame.healthBar, frame.castBar
	local glowRegion, overlayRegion, highlightRegion, levelTextRegion, bossIconRegion, raidIconRegion, stateIconRegion = frame.barFrame:GetRegions()
	local _, castbarOverlay, shieldedRegion, spellIconRegion, castTextRegion, castShadowRegion = castBar:GetRegions()
	local nameTextRegion = frame.nameFrame:GetRegions()

	frame.oldname = nameTextRegion
	nameTextRegion:Hide()

	local newNameRegion = frame:CreateFontString()
	newNameRegion:SetPoint("BOTTOM", healthBar, "TOP", 0, pixelScale(2))
	newNameRegion:SetFont(caelMedia.fonts.CAELNAMEPLATE_FONT, 9 * UIParent:GetScale())
	newNameRegion:SetShadowOffset(1.25, -1.25)
	frame.name = newNameRegion

	frame.level = levelTextRegion

	healthBar:SetStatusBarTexture(caelMedia.files.statusBarC)

	healthBar.hpBackground = healthBar:CreateTexture(nil, "BACKGROUND")
	healthBar.hpBackground:SetAllPoints()
	healthBar.hpBackground:SetTexture(caelMedia.files.statusBarC)

	healthBar.hpGlow = CreateFrame("Frame", nil, healthBar)
	healthBar.hpGlow:SetFrameLevel(healthBar:GetFrameLevel() -1 > 0 and healthBar:GetFrameLevel() -1 or 0)
	healthBar.hpGlow:SetPoint("TOPLEFT", pixelScale(-2), pixelScale(2))
	healthBar.hpGlow:SetPoint("BOTTOMRIGHT", pixelScale(2), pixelScale(-2))
	healthBar.hpGlow:SetBackdrop(caelMedia.backdropTable)
	healthBar.hpGlow:SetBackdropColor(0, 0, 0, 0)
	healthBar.hpGlow:SetBackdropBorderColor(0, 0, 0)

	castBar.castbarOverlay = castbarOverlay
	castBar.healthBar = healthBar
	castBar.shieldedRegion = shieldedRegion
	castBar:SetStatusBarTexture(caelMedia.files.statusBarC)

	castBar:HookScript("OnShow", OnShow)
	castBar:HookScript("OnValueChanged", OnValueChanged)
	castBar:HookScript("OnEvent", OnEvent)
	castBar:HookScript("OnUpdate", FixCastbar)
	castBar:RegisterEvent("UNIT_SPELLCAST_INTERRUPTIBLE")
	castBar:RegisterEvent("UNIT_SPELLCAST_NOT_INTERRUPTIBLE")

	castBar.time = castBar:CreateFontString(nil, "ARTWORK")
	castBar.time:SetPoint("RIGHT", castBar, "LEFT", pixelScale(-2), 0)
	castBar.time:SetFont(caelMedia.fonts.CAELNAMEPLATE_FONT, 9 * UIParent:GetScale())
	castBar.time:SetShadowOffset(1.25, -1.25)

	castBar.cbBackground = castBar:CreateTexture(nil, "BACKGROUND")
	castBar.cbBackground:SetAllPoints()
	castBar.cbBackground:SetTexture(caelMedia.files.statusBarC)
	castBar.cbBackground:SetVertexColor(0.25, 0.25, 0.25, 0.75)

	castBar.cbGlow = CreateFrame("Frame", nil, castBar)
	castBar.cbGlow:SetFrameLevel(castBar:GetFrameLevel() -1 > 0 and castBar:GetFrameLevel() -1 or 0)
	castBar.cbGlow:SetPoint("TOPLEFT", pixelScale(-2), pixelScale(2))
	castBar.cbGlow:SetPoint("BOTTOMRIGHT", pixelScale(2), pixelScale(-2))
	castBar.cbGlow:SetBackdrop(caelMedia.backdropTable)
	castBar.cbGlow:SetBackdropColor(0, 0, 0, 0)
	castBar.cbGlow:SetBackdropBorderColor(0, 0, 0)

	castBar.HolderA = CreateFrame("Frame", nil, castBar)
	castBar.HolderA:SetFrameLevel(castBar:GetFrameLevel() + 1)
	castBar.HolderA:SetAllPoints()

	spellIconRegion:ClearAllPoints()
	spellIconRegion:SetParent(castBar.HolderA)
	spellIconRegion:SetPoint("LEFT", castBar, pixelScale(8), 0)
	spellIconRegion:SetSize(pixelScale(15), pixelScale(15))
	spellIconRegion:SetTexCoord(0.08, 0.92, 0.08, 0.92)

	castBar.HolderB = CreateFrame("Frame", nil, castBar)
	castBar.HolderB:SetFrameLevel(castBar.HolderA:GetFrameLevel() + 2)
	castBar.HolderB:SetAllPoints()

	castBar.IconOverlay = castBar.HolderB:CreateTexture(nil, "OVERLAY")
	castBar.IconOverlay:SetPoint("TOPLEFT", spellIconRegion, pixelScale(-1.5), pixelScale(1.5))
	castBar.IconOverlay:SetPoint("BOTTOMRIGHT", spellIconRegion, pixelScale(1.5), pixelScale(-1.5))
	castBar.IconOverlay:SetTexture(iconTexture)

	castTextRegion:ClearAllPoints()
	castTextRegion:SetPoint("TOP", castBar, "BOTTOM", 0, pixelScale(-5))
	castTextRegion:SetFont(caelMedia.fonts.CAELNAMEPLATE_FONT, 9 * UIParent:GetScale())
	castTextRegion:SetShadowOffset(1.25, -1.25)

	highlightRegion:SetTexture(caelMedia.files.statusBarC)
	highlightRegion:SetVertexColor(0.25, 0.25, 0.25)
	frame.highlight = highlightRegion

	raidIconRegion:ClearAllPoints()
	raidIconRegion:SetPoint("RIGHT", healthBar, pixelScale(-8), 0)
	raidIconRegion:SetSize(pixelScale(15), pixelScale(15))
	raidIconRegion:SetTexture(raidIcons)	

	frame.elite = stateIconRegion
	frame.boss = bossIconRegion

	healthBar.oldglow = glowRegion

	glowRegion:SetTexture(nil)
	overlayRegion:SetTexture(nil)
	shieldedRegion:SetTexture(nil)
	castbarOverlay:SetTexture(nil)
	castShadowRegion:SetTexture(nil)
	stateIconRegion:SetTexture(nil)
	bossIconRegion:SetTexture(nil)

	UpdatePlate(frame)
	frame:SetScript("OnShow", UpdatePlate)
	frame:SetScript("OnHide", OnHide)

	healthBar:SetScript("OnUpdate", HealthUpdate)
end

local index = 1
local lastUpdate = 0
local numKids = 0
caelNameplates.eventFrame:SetScript("OnUpdate", function(self, elapsed)
	lastUpdate = lastUpdate + elapsed

	if lastUpdate > 0.1 then
		lastUpdate = 0

		local newNumKids = WorldFrame:GetNumChildren()
		if newNumKids ~= numKids then
			numKids = WorldFrame:GetNumChildren()
			for i = index, numKids do
				local frame = select(i, WorldFrame:GetChildren())
				local name = frame:GetName()

				if name and name:find("NamePlate") and not frame.done then
					CreatePlate(frame)
					index = i
				end
			end
		end
	end
end)

caelNameplates.eventFrame:SetScript("OnEvent", function(self, event, ...)
	if type(self[event]) == "function" then
		return self[event](self, event, ...)
	end
end)

function caelNameplates.eventFrame:PLAYER_REGEN_ENABLED()
	SetCVar("nameplateShowEnemies", 0)
end

function caelNameplates.eventFrame:PLAYER_REGEN_DISABLED()
	SetCVar("nameplateShowEnemies", 1)
end

caelNameplates.eventFrame:RegisterEvent("ADDON_LOADED")
function caelNameplates.eventFrame:ADDON_LOADED(event, addon)
	if addon and addon:lower() == "caelnameplates" then
		if not caelNameplatesDB then
			caelNameplatesDB = {autotoggle = true}
		end
		
		caelNameplates.settings = caelNameplatesDB
		
		if caelNameplates.settings.autotoggle then
			self:RegisterEvent("PLAYER_REGEN_ENABLED")
			self:RegisterEvent("PLAYER_REGEN_DISABLED")
		end
	end
end

SlashCmdList["caelNameplates"] = function(parameters)
	if parameters == "autotoggle" then
		local newsetting = not caelNameplates.settings.autotoggle
		caelNameplates.settings.autotoggle = newsetting
		
		local func = newsetting and "RegisterEvent" or "UnregisterEvent"
		
		caelNameplates.eventFrame[func](caelNameplates.eventFrame, "PLAYER_REGEN_ENABLED")
		caelNameplates.eventFrame[func](caelNameplates.eventFrame, "PLAYER_REGEN_DISABLED")
		print("Auto toggling of nameplates based on combat state " .. (caelNameplates.settings.autotoggle and "|cff00ff00enabled|r." or "|cffff0000disabled|r."))
	end
end

SLASH_caelNameplates1 = "/caelnameplates"